﻿using System;

namespace TLang.Ast
{
    using Values;

    public class Attr : Node
    {
        public Node value;
        public Name attr;


        public Attr(Node value, Name attr, String file, int start, int end, int line, int col) : base(file, start, end, line, col)
        {
            this.value = value;
            this.attr = attr;
        }

        public override Value Interp(Scope s)
        {
            Value record = value.Interp(s);
            if (record is RecordValue) {
                Value a = ((RecordValue)record).properties.LookupLocal(attr.Id);
                if (a != null)
                {
                    return a;
                }
                else
                {
                    Util.Abort(attr, "attribute " + attr + " not found in record: " + record);
                    return null;
                }
            } else {
                Util.Abort(attr, "getting attribute of non-record: " + record);
                return null;
            }
        }

        public override Value Typecheck(Scope s)
        {
            Value record = value.Typecheck(s);
            if (record is RecordValue) {
                Value a = ((RecordValue)record).properties.LookupLocal(attr.Id);
                if (a != null)
                {
                    return a;
                }
                else
                {
                    Util.Abort(attr, "attribute " + attr + " not found in record: " + record);
                    return null;
                }
            } else {
                Util.Abort(attr, "getting attribute of non-record: " + record);
                return null;
            }
        }


        public void set(Value v, Scope s)
        {
            Value record = value.Interp(s);
            if (record is RecordType) {
                Value a = ((RecordType)record).properties.Lookup(attr.Id);
                if (a != null)
                {
                    ((RecordType)record).properties.PutValue(attr.Id, v);
                }
                else
                {
                    Util.Abort(attr,
                            "can only assign to existing attribute in record, " + attr + " not found in: " + record);
                }
            } else {
                Util.Abort(attr, "setting attribute of non-record: " + record);
            }
        }


        public override String ToString()
        {
            return value + "." + attr;
        }
    }
}
